承上文 在 C# 中 Nullable Reference Types 使用屬性MemberNotNull
我們繼續探討...
使用屬性 MemberNotNullWhen
假設一個例子
class Person
{
static readonly Regex _nameReg = new Regex(@"^I'm \w*");
private string _name;
public Person(string name)
{
if (!TryInitialize(name))
_name = "invalid name";
}
private bool TryInitialize(string name)
{
if (_nameReg.IsMatch(name))
{
_name = name;
return true;
}
else
return false;
}
}
這段程式碼定義了一個類別 Person
,在這個類別中有一個正規表達式物件_nameReg
定義成唯讀與靜態屬性,它是用來匹配名字是否符合特定格式。
類別中還有一個私有字串屬性 _name
和一個建構子方法 public Person(string name)
,建構子方法中有一個判斷式,如果呼叫 TryInitialize
方法傳回的值是 false
,就將 _name
屬性初始化為字串 "invalid name"
。
類別中還有一個私有方法 private bool TryInitialize(string name)
,它會使用 _nameReg
屬性來匹配傳入的名字字串,如果匹配成功就將 _name
屬性初始化為傳入的名字,並傳回布林值。
接著,編譯器將對上面的程式碼發出警告:
警告訊息如下:
警告 CS8618 退出建構函式時,不可為 Null 的 欄位 '_name' 必須包含非 Null 值。請考慮將 欄位 宣告為可為 Null。
按照警告提示他希望你在變數或參數型別前面加上 ?,來表示這個型別可以是空值。例如private string? _name;
但在這個實作中,明明在建構子中將會為 _name
屬性賦值,所以它不可能在建構子結束時為空值。
要解決這種情況,您可以使用屬性MemberNotNullWhen:
[MemberNotNullWhen(true, nameof(_name))]
private bool TryInitialize(string name)
MemberNotNullWhen 屬性是 C# 8.0 中新引入的可空性偵錯工具,
它可以讓你在執行階段確保特定條件下,某個成員不會是空值。
加入後 編譯器的警告 就消失了
如果你嘗試對 _name
屬性進行存取,但是它是空值,則會拋出 NullReferenceException 例外。
這個屬性可以讓你在程式碼中清楚地表達你的意圖,並讓程式在執行階段更穩定。
了解更多:MemberNotNullWhenAttribute Class